package cc.rengu.igas.bsps.core.service.trans;

import cc.rengu.igas.bsps.common.constant.BspsAppParamConstant;
import cc.rengu.igas.bsps.common.constant.BspsManageConstant;
import cc.rengu.igas.bsps.common.dao.*;
import cc.rengu.igas.bsps.common.dao.impl.*;
import cc.rengu.igas.bsps.common.entity.AgentInfo;
import cc.rengu.igas.bsps.common.entity.ManagerInfo;
import cc.rengu.igas.bsps.common.entity.UserLoginInfo;
import cc.rengu.igas.bsps.common.entity.UserRoleInfo;
import cc.rengu.igas.bsps.common.enums.AuthTypeEnum;
import cc.rengu.igas.bsps.common.enums.BspsLoginTypeEnum;
import cc.rengu.igas.bsps.common.enums.RespCodeEnum;
import cc.rengu.igas.bsps.core.model.UserSessionInfo;
import cc.rengu.igas.bsps.core.service.base.BankManagerService;
import cc.rengu.igas.bsps.facade.base.Header;
import cc.rengu.igas.bsps.facade.bean.PrivilegeInfoBean;
import cc.rengu.igas.bsps.facade.request.ManagerAuthRequest;
import cc.rengu.igas.bsps.facade.response.ManagerAuthResponse;
import cc.rengu.igas.channel.wechat.facade.request.ExpandManagerMsgPushRequest;
import cc.rengu.oltp.service.common.constant.AppConfigConstant;
import cc.rengu.oltp.service.common.constant.AppParamConstant;
import cc.rengu.oltp.service.common.constant.TreeNodeConstant;
import cc.rengu.oltp.service.common.enums.ChannelEnum;
import cc.rengu.oltp.service.common.enums.OltpRpcdEnum;
import cc.rengu.oltp.service.common.enums.SmsTypeEnum;
import cc.rengu.oltp.service.model.BizException;
import cc.rengu.oltp.service.model.BizResponse;
import cc.rengu.oltp.service.realize.DubboService;
import cc.rengu.oltp.service.realize.SmsService;
import cc.rengu.oltp.service.realize.impl.DubboServiceImpl;
import cc.rengu.oltp.service.realize.impl.SmsServiceImpl;
import cc.rengu.oltp.utility.util.*;
import com.alibaba.fastjson.JSON;
import org.springframework.util.CollectionUtils;

import java.util.ArrayList;
import java.util.List;

import static com.alibaba.fastjson.JSON.toJSONString;

/**
 * @author zhangxuran
 * @version 1.0
 * @date 2020/04/05
 */
public class ManagerAuthService extends BankManagerService {
    private BspsManagerInfoMapper bspsManagerInfoMapper = new BspsManagerInfoMapperImpl();
    private BspsUserInfoMapper bspsUserInfoMapper = new BspsUserInfoMapperImpl();
    private BspsUserLoginInfoMapper bspsUserLoginInfoMapper = new BspsUserLoginInfoMapperImpl();

    @Override
    protected Object bizBeforeCust() throws Exception {
        ManagerAuthRequest managerAuthRequest = new ManagerAuthRequest();
        ConvertUtil.convertOutput(managerAuthRequest);
        return managerAuthRequest;
    }

    @Override
    protected BizResponse bizProcessCust(Object request) throws Exception {
        ManagerAuthRequest managerAuthRequest = (ManagerAuthRequest) request;
        ManagerAuthResponse managerAuthResponse = new ManagerAuthResponse();
        /*获取请求参数信息：法人行号，用户openId，认证类型，拓展经理姓名，拓展经理手机号，短信验证码，验证码唯一标识*/
        String instId = managerAuthRequest.getHeader().getInstId();
        String openId = managerAuthRequest.getOpenId();
        String authType = managerAuthRequest.getAuthType();
        String managerName = managerAuthRequest.getManagerName();
        String managerPhone = managerAuthRequest.getManagerPhone();
        String smsCode = managerAuthRequest.getSmsCode();
        String smsAuthId = managerAuthRequest.getSmsAuthId();
        String channelId = managerAuthRequest.getHeader().getChanlId();
        /*必填项校验*/
        rglog.info("拓展经理认证登录必填校验");
        if (StringUtil.isEmptyOrNull(authType) || StringUtil.isEmptyOrNull(instId)) {
            rglog.error("请求参数校验必填字段失败！");
            throw new BizException(RespCodeEnum.MSG_VALID_CHECK_ERROR.getRespCode(), RespCodeEnum.MSG_VALID_CHECK_ERROR.getRespDesc());
        }
        /*拓展经理认证绑定或者登录都需要先查询拓展经理信息，再根据角色返回权限信息*/
        ManagerInfo managerInfo;
        /*认证绑定时拓展经理信息及短信信息必填*/
        if (AuthTypeEnum.AUTH_BIND.getAuthType().equals(authType)) {
            rglog.info("拓展经理认证操作开始");
            if (StringUtil.isEmptyOrNull(openId) || StringUtil.isEmptyOrNull(managerName) ||
                    StringUtil.isEmptyOrNull(managerPhone) || StringUtil.isEmptyOrNull(smsCode) || StringUtil.isEmptyOrNull(smsAuthId)) {
                rglog.error("请求参数校验必填字段失败！");
                throw new BizException(RespCodeEnum.MSG_VALID_CHECK_ERROR.getRespCode(), RespCodeEnum.MSG_VALID_CHECK_ERROR.getRespDesc());
            }
            rglog.info("短信验证码校验");
            /*1-验证短信验证码*/
            SmsService smsService = new SmsServiceImpl();
            boolean smsFlag = smsService.verifySmsCode(instId, SmsTypeEnum.USER_REGISTER.getSmsType(), smsCode, smsAuthId);
            if (!smsFlag) {
                rglog.error("短信验证码校验失败！");
                throw new BizException(OltpRpcdEnum.VERIFY_SMS_CODE_ERROR.getRespCode(), OltpRpcdEnum.VERIFY_SMS_CODE_ERROR.getRespDesc());
            }
            rglog.info("拓展经理信息更新");
            /*2-查询拓展经理信息，更新拓展经理信息表中openId*/
            /*查询更新拓展经理信息*/
            managerInfo = bspsManagerInfoMapper.selectBspsManagerInfoByNameAndPhone(instId, managerName, managerPhone);
            if (null == managerInfo) {
                rglog.error("拓展经理信息不存在！");
                throw new BizException(RespCodeEnum.GET_MANAGER_INFO_ERROR.getRespCode(), RespCodeEnum.GET_MANAGER_INFO_ERROR.getRespDesc());
            }
            if (!"OPENID".equals(managerInfo.getOpenId())) {
                rglog.error("拓展经理信息已绑定！");
                throw new BizException(RespCodeEnum.MANAGER_EXIST_ERROR.getRespCode(), RespCodeEnum.MANAGER_EXIST_ERROR.getRespDesc());
            }
            /*赋值微信openId*/
            managerInfo.setOpenId(openId);
            /*默认最后操作人员ID*/
            managerInfo.setLastOprId(BspsManageConstant.SYSTEM_USER_ID);
            /*最后操作时间*/
            managerInfo.setLastUpdateTime(DateUtil.getCurrentDateTime(BspsAppParamConstant.yyyy_MM_dd_HHmmssSSS));

            //拓展经理认证消息推送
            String titleType = "T00";
            //拓展经理角色判断
            if ("41".equals(managerInfo.getRoleType())) {
                titleType = "T01";
            }
            XmlTreeUtil xmlTreeUtil = new XmlTreeUtil();
            ExpandManagerMsgPushRequest expandManagerMsgPushRequest = new ExpandManagerMsgPushRequest();
            cc.rengu.igas.channel.wechat.facade.base.Header wxchatHeader = new cc.rengu.igas.channel.wechat.facade.base.Header();
            wxchatHeader.setInstId(instId);
            wxchatHeader.setVersion("1.0.0");
            wxchatHeader.setBizType("00");
            wxchatHeader.setTransDate(DateUtil.getCurrentDate());
            wxchatHeader.setTransTime(DateUtil.getCurrentTime());
            wxchatHeader.setSrcSysId(AppParamConstant.SYS_ID);
            wxchatHeader.setChanlId(ChannelEnum.BSPS.getChannelType());
            wxchatHeader.setTxnNum("expandmanager");
            wxchatHeader.setTraceNo(xmlTreeUtil.getXmlTreeStringValue(TreeNodeConstant.SYS_SEQ_NUM));
            expandManagerMsgPushRequest.setHeader(wxchatHeader);
            expandManagerMsgPushRequest.setChannelId(ChannelEnum.WXZF.getChannelType());
            expandManagerMsgPushRequest.setAuthTime(DateUtil.getCurrentDateTime("yyyy-MM-dd HH:mm:ss"));
            expandManagerMsgPushRequest.setEmpNo(managerInfo.getManagerId());
            expandManagerMsgPushRequest.setEmpName(managerName);
            expandManagerMsgPushRequest.setTitleType(titleType);
            expandManagerMsgPushRequest.setOpenId(openId);
            /*需要配置异步服务*/
            DubboService dubboService = new DubboServiceImpl();
            int dubboReturnCode = dubboService.asynCallDubboService("wechatMsgPushService", "expandManagerMsgPush", expandManagerMsgPushRequest, null);
            if (0 != dubboReturnCode) {
                rglog.error("拓展经理认证公众号消息推送失败！");
            }
        } else if (AuthTypeEnum.AUTH_LOGIN.getAuthType().equals(authType)) {
            rglog.info("用户登录操作");
            if (StringUtil.isEmptyOrNull(openId)) {
                rglog.error("请求参数校验必填字段失败！");
                throw new BizException(RespCodeEnum.MSG_VALID_CHECK_ERROR.getRespCode(), RespCodeEnum.MSG_VALID_CHECK_ERROR.getRespDesc());
            }
            managerInfo = bspsManagerInfoMapper.selectBspsManagerInfoByOpenId(instId, openId);
            if (null == managerInfo) {
                rglog.error("根据openId<{}>查询拓展经理信息失败！", openId);
                throw new BizException(RespCodeEnum.GET_MANAGER_INFO_ERROR.getRespCode(), RespCodeEnum.GET_MANAGER_INFO_ERROR.getRespDesc());
            }
        } else if (AuthTypeEnum.MOBILE_LOGIN.getAuthType().equals(authType)) {
            rglog.info("员工号登录操作");
            if (StringUtil.isEmptyOrNull(managerPhone) || StringUtil.isEmptyOrNull(smsCode) || StringUtil.isEmptyOrNull(smsAuthId)) {
                rglog.error("请求参数校验必填字段失败！");
                throw new BizException(RespCodeEnum.MSG_VALID_CHECK_ERROR.getRespCode(), RespCodeEnum.MSG_VALID_CHECK_ERROR.getRespDesc());
            }
            /*1-验证短信验证码*/
            SmsService smsService = new SmsServiceImpl();
            boolean smsFlag = smsService.verifySmsCode(instId, SmsTypeEnum.USER_LOGIN.getSmsType(), smsCode, smsAuthId);
            if (!smsFlag) {
                rglog.error("短信验证码校验失败！");
                throw new BizException(OltpRpcdEnum.VERIFY_SMS_CODE_ERROR.getRespCode(), OltpRpcdEnum.VERIFY_SMS_CODE_ERROR.getRespDesc());
            }
            /*2-根据手机号查询拓展经理信息 */
            managerInfo = bspsManagerInfoMapper.selectBspsManagerInfoByManagerPhone(instId, managerPhone);
            if (null == managerInfo) {
                rglog.error("根据managerPhone<{}>查询拓展经理信息失败！", managerPhone);
                throw new BizException(RespCodeEnum.GET_MANAGER_INFO_ERROR.getRespCode(), RespCodeEnum.GET_MANAGER_INFO_ERROR.getRespDesc());
            }
            /* 手机号登录时，使用记录的ID作为用户标识返回 */
            managerInfo.setOpenId(managerInfo.getId());
        } else {
            rglog.error("认证类型参数错误！");
            throw new BizException(RespCodeEnum.MSG_VALID_CHECK_ERROR.getRespCode(), RespCodeEnum.MSG_VALID_CHECK_ERROR.getRespDesc());
        }
        /*根据用户角色查询用户权限列表*/
        BspsUserRoleInfoMapper bspsUserRoleInfoMapper = new BspsUserRoleInfoMapperImpl();
        List<UserRoleInfo> userRoleInfoList = bspsUserRoleInfoMapper.selectBspsUserRoleInfoToChannelMenu(instId, managerInfo.getRoleType(), channelId);
        List<PrivilegeInfoBean> privilegeInfoList = new ArrayList<>();
        if (!CollectionUtils.isEmpty(userRoleInfoList)) {
            for (UserRoleInfo userRoleInfo : userRoleInfoList) {
                PrivilegeInfoBean privilegeInfo = new PrivilegeInfoBean();
                /*菜单标识赋值*/
                privilegeInfo.setMenuId(userRoleInfo.getMenuId());
                /*菜单名称赋值*/
                privilegeInfo.setMenuName(userRoleInfo.getMenuName());
                /*菜单页面路径赋值*/
                privilegeInfo.setMenuUrlPath(userRoleInfo.getMenuUrlPath());
                /*功能权限标识说明*/
                privilegeInfo.setFuncDroitId(userRoleInfo.getFuncDroitId());
                /*功能权限说明*/
                privilegeInfo.setFuncDroitDesc(userRoleInfo.getFuncDroitDesc());
                BeanUtil.beanCopy(userRoleInfo, privilegeInfo);
                privilegeInfoList.add(privilegeInfo);
            }
        }
        /*新增用户登录信息*/

        UserLoginInfo userLoginInfo = new UserLoginInfo();
        /*法人行赋值*/
        userLoginInfo.setInstId(instId);
        /*登录方式赋值*/
        userLoginInfo.setLoginType(BspsLoginTypeEnum.OPEN_ID.getLoginType());
        /*用户标识赋值*/
        userLoginInfo.setUserId(managerInfo.getOpenId());
        /*登录时间赋值*/
        userLoginInfo.setLoginTime(DateUtil.getCurrentDateTime("yyyy-MM-dd HH:mm:ss.SSS"));
        /*最后操作时间赋值*/
        userLoginInfo.setLastOprTime(DateUtil.getCurrentDateTime("yyyy-MM-dd HH:mm:ss.SSS"));
        /*登录状态赋值*/
        userLoginInfo.setLoginStatus("0");
        userLoginInfo.setSessionId(managerAuthRequest.getHeader().getSession());
        /*认证绑定操作*/
        if (AuthTypeEnum.AUTH_BIND.getAuthType().equals(authType)) {
            bindManagerInfo(userLoginInfo, managerInfo);
        } else if (AuthTypeEnum.AUTH_LOGIN.getAuthType().equals(authType) || AuthTypeEnum.MOBILE_LOGIN.getAuthType().equals(authType)) {
            /*登录操作*/
            managerLogin(userLoginInfo);
        } else {
            rglog.error("操作类型错误！");
            throw new BizException(RespCodeEnum.NOT_SUPPORT_ORT_TYPE.getRespCode(), RespCodeEnum.NOT_SUPPORT_ORT_TYPE.getRespDesc());
        }
        /*将用户信息和拓展经理信息放入redis缓存中*/
        Header header = managerAuthRequest.getHeader();
        String sessionKey = header.getSession();
        UserSessionInfo keySessionInfo = JSON.parseObject(RedisUtil.onceGet(sessionKey), UserSessionInfo.class);
        if (null == keySessionInfo) {
            rglog.error("session为空，异常");
            throw new BizException(RespCodeEnum.USER_NOT_LOGIN_OR_SESSION_IS_EXPIRED.getRespCode(), RespCodeEnum.USER_NOT_LOGIN_OR_SESSION_IS_EXPIRED.getRespDesc());
        }
        keySessionInfo.setUserId(managerInfo.getOpenId());
        RedisUtil.onceSet(sessionKey, toJSONString(keySessionInfo), BspsAppParamConstant.SESSION_EFFECTIVE_TIME);
        //生成新的会话id
        String newSessionId = RandomUtil.getUUID();
        UserSessionInfo userSessionInfo = new UserSessionInfo();
        userSessionInfo.setUserId(managerInfo.getOpenId());
        userSessionInfo.setSignatureKey(keySessionInfo.getSignatureKey());
        userSessionInfo.setSensitiveKey(keySessionInfo.getSensitiveKey());
        RedisUtil.onceSet(newSessionId, toJSONString(userSessionInfo), BspsAppParamConstant.SESSION_EFFECTIVE_TIME);
        header.setSession(newSessionId);
        managerAuthResponse.setHeader(header);

        RedisUtil.onceSet(managerInfo.getInstId() + managerInfo.getManagerId(), toJSONString(managerInfo));
        /*用户标识赋值*/
        managerAuthResponse.setUserImagePath(managerInfo.getUserImagePath());
        /*拓展经理用户ID赋值*/
        managerAuthResponse.setUserId(managerInfo.getOpenId());
        /*拓展经理员工号赋值*/
        managerAuthResponse.setManagerId(managerInfo.getManagerId());
        /*拓展经理姓名赋值*/
        managerAuthResponse.setManageName(managerInfo.getManagerName());
        /*拓展经理手机号赋值*/
        managerAuthResponse.setManagerPhone(managerInfo.getManagerPhone());
        /*拓展经理角色赋值*/
        managerAuthResponse.setUserRole(managerInfo.getRoleType());
        /*角色权限赋值*/
        managerAuthResponse.setPrivilegeInfoList(privilegeInfoList);
        /*拓展经理签约机构类型*/
        managerAuthResponse.setSignInstType(managerInfo.getSignInstType());
        /*拓展经理所属机构*/
        rglog.info("拓展经理类型" + managerInfo.getSignInstType());
        if ("BANK".equals(managerInfo.getSignInstType())) {
            rglog.info("行方拓展经理");
            managerAuthResponse.setSignInstId(managerInfo.getSignInstId());
        } else if ("AGENT".equals(managerInfo.getSignInstType())) {
            rglog.info("代理机构拓展经理");
            BspsAgentInfoMapper bspsAgentInfoMapper = new BspsAgentInfoMapperImpl();
            AgentInfo agentInfo = bspsAgentInfoMapper.selectBspsAgentInfoByInstIdAndAgentCode(instId, managerInfo.getSignInstId());
            if (null != agentInfo) {
                managerAuthResponse.setSignInstId(agentInfo.getManageInstId());
                managerAuthResponse.setAgentOrgId(agentInfo.getAgentCode());
            } else {
                rglog.error("未查询到拓展经理所属代理机构");
            }
        } else {
            rglog.error("拓展经理类型错误");
        }

        /*拼装返回报文信息*/
        BizResponse<ManagerAuthResponse> bizResponse = new BizResponse<>();
        bizResponse.setRspSysId(AppParamConstant.SYS_ID);
        bizResponse.setRespCode(RespCodeEnum.TRANS_SUCCESS.getRespCode());
        bizResponse.setRespDesc(RespCodeEnum.TRANS_SUCCESS.getRespDesc());
        bizResponse.setResult(managerAuthResponse);
        return bizResponse;
    }

    /**
     * 拓展经理认证绑定操作
     *
     * @param userLoginInfo 用户登录信息
     * @param managerInfo   拓展经理信息
     */
    private void bindManagerInfo(UserLoginInfo userLoginInfo, ManagerInfo managerInfo) throws Exception {
        int iReturnCode;
        /*更新拓展经理openId*/
        iReturnCode = bspsManagerInfoMapper.updateBspsManagerInfoById(managerInfo);
        if (0 != iReturnCode) {
            rglog.error("拓展经理信息更新失败！");
            throw new BizException(RespCodeEnum.UPDATE_MANAGER_INFO_ERROR.getRespCode(), RespCodeEnum.UPDATE_MANAGER_INFO_ERROR.getRespDesc());
        }
        /* 开启数据库事务 */
        XmlTreeUtil xmlTreeUtil = new XmlTreeUtil();
        String dbPoolName = XmlConfigUtil.getXmlConfigCacheKeyValue(AppConfigConstant.DATABASE_CONF_NODE, AppConfigConstant.OLTP_POOL_NAME);
        String corporation = xmlTreeUtil.getXmlTreeStringValue(AppParamConstant.CORPORATION);
        if (null != corporation && !corporation.isEmpty()) {
            String dbPoolCashNode = corporation.trim() + AppParamConstant.DATABASE_CONF_NODE;
            dbPoolName = XmlConfigUtil.getXmlConfigCacheKeyValue(dbPoolCashNode, AppConfigConstant.OLTP_POOL_NAME);
        }
        DbsUtil dbsUtil = new DbsUtil(dbPoolName);
        dbsUtil.dbsBeginTransaction();

        /*新增用户登录信息*/
        iReturnCode = bspsUserLoginInfoMapper.insertBspsUserLoginInfo(userLoginInfo);
        if (0 != iReturnCode) {
            dbsUtil.dbsEndTransaction(false);
            rglog.error("用户登录信息新增失败！");
            throw new BizException(RespCodeEnum.REGISTER_USER_LOGIN_INFO_ERROR.getRespCode(), RespCodeEnum.REGISTER_USER_LOGIN_INFO_ERROR.getRespDesc());
        }
        dbsUtil.dbsEndTransaction(true);
    }

    /**
     * 商户登录记录新增操作
     *
     * @param userLoginInfo 商户登录信息
     **/
    private void managerLogin(UserLoginInfo userLoginInfo) throws Exception {
        /* 开启数据库事务 */
        XmlTreeUtil xmlTreeUtil = new XmlTreeUtil();
        String dbPoolName = XmlConfigUtil.getXmlConfigCacheKeyValue(AppConfigConstant.DATABASE_CONF_NODE, AppConfigConstant.OLTP_POOL_NAME);
        String corporation = xmlTreeUtil.getXmlTreeStringValue(AppParamConstant.CORPORATION);
        if (null != corporation && !corporation.isEmpty()) {
            String dbPoolCashNode = corporation.trim() + AppParamConstant.DATABASE_CONF_NODE;
            dbPoolName = XmlConfigUtil.getXmlConfigCacheKeyValue(dbPoolCashNode, AppConfigConstant.OLTP_POOL_NAME);
        }
        DbsUtil dbsUtil = new DbsUtil(dbPoolName);
        dbsUtil.dbsBeginTransaction();
        /*新增用户登录信息*/
        int iReturnCode = bspsUserLoginInfoMapper.insertBspsUserLoginInfo(userLoginInfo);
        if (0 != iReturnCode) {
            dbsUtil.dbsEndTransaction(false);
            rglog.error("用户登录信息新增失败！");
            throw new BizException(RespCodeEnum.REGISTER_USER_LOGIN_INFO_ERROR.getRespCode(), RespCodeEnum.REGISTER_USER_LOGIN_INFO_ERROR.getRespDesc());
        }
        dbsUtil.dbsEndTransaction(true);
    }

    @Override
    protected void bizAfterCust(Object response) throws Exception {
        BizResponse bizResponse = (BizResponse) response;
        ManagerAuthResponse managerAuthResponse = (ManagerAuthResponse) bizResponse.getResult();
        ConvertUtil.convertInput(managerAuthResponse);
    }
}
